/*
 * @Author: Damon Liu
 * @Date: 2025-04-28 17:00:25
 * @LastEditors: Damon Liu
 * @LastEditTime: 2025-04-29 14:38:55
 * @Description: 
 */
import dayjs from 'dayjs'
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'

dayjs.extend(isSameOrBefore)

/**
 * 展开循环日程，将循环日程转换为具体的时间实例
 * @param {Array} schedules - 原始日程列表
 * @param {string} fromDate - 开始日期
 * @param {string} toDate - 结束日期
 * @returns {Array} 展开后的日程列表，包含所有循环日程的具体实例
 */
export function expandRecurringSchedules(schedules, fromDate, toDate) {
    const result = [];
    // 将日期字符串转换为 dayjs 对象以便于处理
    const dFrom = dayjs(fromDate)
    const dTo = dayjs(toDate)
    
    schedules.forEach(schedule => {
        // 处理非循环日程
        if (!schedule.repeatType || schedule.repeatType === 'none') {
            // 非循环日程直接加入结果列表
            result.push(schedule);
        } else {
            // 处理循环日程
            // 获取原始日程的时间信息
            const originStart = dayjs(schedule.start)
            const originEnd = dayjs(schedule.end)
            const originReminder = schedule.reminder ? dayjs(schedule.reminder) : null
            // 获取循环结束时间，如果没有设置则使用查询结束时间
            const repeatEnd = schedule.repeatEnd ? dayjs(schedule.repeatEnd) : dTo
            // 获取循环间隔，默认为1
            const interval = schedule.repeatInterval || 1

            // 确定循环的起始点
            // 如果查询开始时间晚于原始开始时间，则从查询开始时间开始
            let current = dFrom.isAfter(originStart) ? dFrom : originStart
            // 只保留日期部分，忽略具体时间
            current = current.startOf('day')

            // 循环生成日程实例，直到超过结束时间或循环结束时间
            while (current.isSameOrBefore(dTo) && current.isSameOrBefore(repeatEnd)) {
                let shouldAdd = false;
                
                // 根据循环类型判断当前日期是否需要添加日程
                if (schedule.repeatType === 'daily') {
                    // 每天循环
                    shouldAdd = true;
                } else if (schedule.repeatType === 'weekly') {
                    // 每周循环，检查是否在指定的星期几
                    // repeatDays: [0,1,2,3,4,5,6] 0=周日
                    if (Array.isArray(schedule.repeatDays) && schedule.repeatDays.includes(current.day())) {
                        shouldAdd = true;
                    }
                } else if (schedule.repeatType === 'monthly') {
                    // 每月循环，检查是否在指定的日期
                    if (current.date() === originStart.date()) {
                        shouldAdd = true;
                    }
                }

                if (shouldAdd) {
                    // 创建新的日程实例
                    // 使用当前日期 + 原始开始时间的时分秒
                    const instanceStart = current
                        .hour(originStart.hour())
                        .minute(originStart.minute())
                        .second(originStart.second())
                        .millisecond(originStart.millisecond())
                    
                    // 计算持续时间并设置结束时间
                    const duration = originEnd.diff(originStart)
                    const instanceEnd = instanceStart.add(duration, 'millisecond')
                    
                    // 计算提醒时间
                    let instanceReminder = ''
                    if (originReminder) {
                        const reminderOffset = originReminder.diff(originStart)
                        instanceReminder = instanceStart.add(reminderOffset, 'millisecond').toISOString()
                    }

                    // 将新生成的日程实例添加到结果列表
                    result.push({
                        ...schedule,
                        start: instanceStart.toISOString(),
                        end: instanceEnd.toISOString(),
                        reminder: instanceReminder,
                        // originalId: schedule.id
                    })
                }

                // 移动到下一个可能的日期
                if (schedule.repeatType === 'daily') {
                    current = current.add(interval, 'day')
                } else if (schedule.repeatType === 'weekly') {
                    current = current.add(1, 'day')
                } else if (schedule.repeatType === 'monthly') {
                    current = current.add(interval, 'month')
                } else {
                    break;
                }
            }
        }
    });
    return result;
}